/**
 * @author Rid King
 * @since 2017-06-02
 * @version 2.0.0
 * @description 超时操作符
 */
'user strict';

import Operator from '../operator.js'

/**
 * @description 超时执行
 * @param executor <Executor> // 执行者
 * [@param num <int> 重复次数，默认1次]
 * [@param time <int> 时间毫秒数，默认5000毫秒]
 * */
class TimeoutOperator extends Operator {
    /**
     * @description 获取操作名称
     * @return <String>
    */
    static getName () {
        return 'timeout'
    }

    /**
     * @description 管道方法
    */
    pipe () {
        // 次数过滤
        let num = parseInt(this._args[0])
        num = isNaN(num) ? 1 : num
        num = num < 0 ? 0 : num

        // 时间过虑
        let time = parseInt(this._args[1])
        time = isNaN(time) ? 5000 : time
        time = time < 0 ? 0 : time

        // 获取操作者
        let executor = this._executor

        let me = this
        // 消费参数
        let args = arguments
        // 重置执行次数
        this.times = 0
        // 清除定时器
        if (this.timer) {
            clearTimeout(this.timer)
        }
        // 获取操作序号
        let order = executor.getOrder()
        // 是否取消，决定是否执行下一操作
        let isCancel = false

        // 定时器
        function timer () {
            // 创建定时器
            me.timer = setTimeout(() => {
                // 已取消不执行
                if (isCancel) {
                    return false
                }

                // 检测执行次数
                if (me.times >= num) {
                    delete me.timer
                    return false
                }

                // 执行次数累加
                me.times += 1

                // 如果下一步状态未改变
                if (executor.getOrder() === order + 1 && !executor.isLastOrder()) {
                    // 执行定时任务
                    timer.bind(this)()
                    // 撤回当前操作
                    executor.recall().next.apply(executor, args)
                } else {
                    delete me.timer
                }
            }, time)
        }

        // 执行定时任务
        timer.bind(this)()

        // 执行下一步
        executor.next.apply(executor, args)

        // 取消操作
        return {
            recall () {
                clearTimeout(me.timer)
                isCancel = true
            }
        }
    }
}

export default TimeoutOperator